#include <QtGui>
#include "Spreadsheet.h"
#include "Helper.h"
#include <vector>
#include <string>
using namespace std;

//#include "CVSElapsedTimer.h"
#include "Data.h"
#define _USE_MATH_DEFINES // this makes sure M_PI will be defined
#include <math.h>
#include "fileIO.h"
#include <Windows.h>

#define FLYBOX_WAIT_IF_LESS_THAN_TIME 5
#define FLYBOX_WAIT_TIME 5

bool CData::_bFlyBoxConnected = false;

int                _nScriptIdx=0;

CData::CData()
{
   setXPosition() = 0;
   setTimer() = 0;
}

CData::~CData()
{
    clear();
    CleanUp();
}

bool CData::CheckForTriggerHelper()
{
    return true;
}

void CData::load(const vector<CSpreadsheet*> &vSpreadsheet_ )
{
    clear();

    //load init file
    {
        CSpreadsheet *pInit;
        for(unsigned int i=0;i<vSpreadsheet_.size();i++)
        {
            if(vSpreadsheet_[i]->currentFile().contains(".init"))
                pInit = vSpreadsheet_[i];
        }
        if(!pInit)
        {
            QString sError("Init File : cannot find any init file.\n \"");
            sError += pInit->currentFile();
            sError += "\".\n";
            throw exception(sError.toStdString().c_str());
        }
        vector<double> vIn;
        pInit->search("TexScale",&setTexScale());       
        pInit->search("GfxBackColor",3,&setBackColor());      
        pInit->search("GfxFOVy",&setGfxFOVy());           
        pInit->search("GfxAspectRatio",&setGfxAspectRatio());
        double dFOVy_RADd2 = gfxFOVy()/2.*DEG2RAD;
        double dFOVx_RADd2 = atan(tan(dFOVy_RADd2)*gfxAspectRatio());
        setGfxFOVx() = (float)dFOVx_RADd2*2*RAD2DEG;

        pInit->search("GfxNear",&setGfxNear());           
        pInit->search("GfxFar",&setGfxFar()); 
        pInit->search("GfxEyeHeight",&setEyeHeight());    
        pInit->search("ExptFlyBoxEnabled",&setFlyBox());   
      
        double dNear = eyeHeight()/tan(gfxFOVy()/2*DEG2RAD);
        if (gfxNear() < dNear)
        {
            // correct near clipping plane to what is visible inside screen
            setGfxNear() = dNear;
            QMessageBox::warning(NULL,QString("Init File"),QString("Near Plane adjusted."),QMessageBox::Yes);
            //std::cout << "Near Plane adjusted to: " << dNear << "m" << std::endl;
        }


        string strIn;
        pInit->search("TexFileName",1,&strIn);      setTexFileName().push_back(strIn);
        pInit->search("TexFileName",2,&strIn);      setTexFileName().push_back(strIn);
        pInit->search("OutputFileName",1,&setOutputFileName());   
        pInit->search("SystemOutput",&setSystemOutput() );   
        pInit->search("ScriptFileName",1,&strIn);   setScriptFileName() = QString(strIn.c_str());
        pInit->search("SecondstoBreak",1,&vIn);     setBreakTime() = vIn[0];
        pInit->search("ExperimenterName",1,&strIn); setExperimenter() = QString(strIn.c_str());
        pInit->search("Telephone",1,&strIn);        setTel() = QString(strIn.c_str());
        pInit->search("CheckFrameRate",&setCheckFrameRate()); 
    }
    // load script file
    {
        CSpreadsheet *pScript; vector<double> vIn;
        vector<CSpreadsheet*> vpScript;

        for(unsigned int i=0;i<vSpreadsheet_.size();i++)
        {
            if(vSpreadsheet_[i]->currentFile().contains(".scr"))
            {
                pScript = vSpreadsheet_[i];
                vpScript.push_back(pScript);
            }
        }
        if(vpScript.empty())
        {
            QString sError("Script File : cannot find any script file.\n \"");
            sError += "\".\n";
            throw exception(sError.toStdString().c_str());
        }

        _nScriptIdx =0 ;
        while(!vpScript[_nScriptIdx]->getCurrentFile().contains(scriptFileName()))
        {
            _nScriptIdx++;
            if(_nScriptIdx>=(int)vpScript.size())
            {
                QString sError("Script File : cannot find the script file: ");
                sError += pScript->currentFile();
                sError += "\".\n";
                throw exception(sError.toStdString().c_str());
            }
        };
        
        pScript = vpScript[_nScriptIdx];
        pScript->searchMatrix("#Script",&setRunScript());
        //pScript->search("#Block Size",1,&vIn); setBlockSize() = (int)vIn[0];
        vector<string>     vConditionScript;
        pScript->searchColumnString("#Condition",&vConditionScript);
        setConditionScript().assign(vConditionScript.begin(),vConditionScript.begin()+GetRunScript().Rows());
        vector<int>        vConditionNum;
        pScript->searchColumnInt("#ConditionNum",&vConditionNum);
        if(vConditionNum.size()!=GetRunScript().Rows())
            throw exception("the rows of ConditionNum and those of Script matrix should match.");
        setConditionNumScript().assign(vConditionNum.begin(),vConditionNum.begin()+GetRunScript().Rows());
        
        // output the script info to system output.
        CFileIO cFIO;
        // check existence data directory and create if necessary
        cFIO.CreateCWDir(string("\\data")); // do not add trailing slash! (prefixing a slash is not necessary but ok

        // create filename: prefix + _ ellipse _ + control condition + feedback condition + run# + option training flag
        char cFileName[80];
        sprintf_s(cFileName,80,"System_Output.txt");

        // create file
        cFIO.OpenFileWrite(cFileName);
        {
            // inputs from file and other fixed parameters
            cFIO.WriteStrValToFile(string("Script Idx:"));
            cFIO.WriteTab();
            cFIO.WriteIntValToFile(_nScriptIdx);
            cFIO.WriteEndl();
            cFIO.WriteStrValToFile(pScript->currentFile().toStdString());
            cFIO.WriteEndl();
            cFIO.CloseFile();
        }
    }
    return;
}

void CData::disConnectFlyBox()
{
    //if(_bFlyBoxConnected)
    //    if(flyBox())
    //    {    
    //        _cFly.rf_quit();
    //        _bFlyBoxConnected = false;
    //        setFlyBox() = false;
    //    }
}

void CData::clear()
{
    _mRunScript.CleanUp();
    _vBackColor.clear(); 
    _vTexColor.clear(); 
    _vstrTexFileName.clear();
}
void CData::updateOutput(int nJoySticky_/*=0*/)
{
    return;
}

bool CData::allTrialsFinished()
{
    return trialIdx()>=GetRunScript().Rows();
}

void CData::precompute()
{
    return;
}

void CData::precomputeEachTrial()
{
    return;
}

void CData::afterCompute()
{

}

void CData::fullOutputFileName(int nTrial_,QString* pFullOutputFileName_) const
{
    pFullOutputFileName_->clear();
    string strCond = conditionScript()[nTrial_];
    double dForwardVelocity = GetRunScript()(nTrial_,1);

    // create filename: ClassName_subjectName_trialIdx_v3_d1_UG+CL+T.txt

    *pFullOutputFileName_= QString("%1_%2_%3_v%4_%5.txt")
        .arg(className().c_str())
        .arg(outputFileName().c_str())
        .arg(nTrial_%blockSize())
        .arg(dForwardVelocity)
        .arg(strCond.c_str());

    return;
}

void CData::computeEyePositionAndGazing( CMatrix<double>& mEye_,CMatrix<double>& mGazingPoint_,int nCurrentFrame_ )
{
    ;
}


void CData::CleanUp()
{
    ;
}